Skip to content

Route API User Agents by Actual Provider Target#976

Open
jatmn wants to merge 6 commits intoGitlawb:mainfrom
hicap-oss:api-client-version
Open

Route API User Agents by Actual Provider Target#976
jatmn wants to merge 6 commits intoGitlawb:mainfrom
hicap-oss:api-client-version

Conversation

@jatmn
Copy link
Copy Markdown
Collaborator

@jatmn jatmn commented May 2, 2026

Warning

Do not approve this PR until @kevincodex1 has confirmation from moonshot.ai that the KimiCode provider no longer blocks openclaude-cli.

Summary

This PR fixes how OpenClaude reports its client identity across different network paths.

Previously, the code mixed together:

  • Anthropic compatibility traffic, which must keep the upstream-compatible claude-cli identity and compatibility version
  • non-first-party/OpenAI-compatible traffic, which should identify as openclaude-cli and use the current public build version

This change separates those cases so each request path reports the correct client name and version.

What Changed

1. Split Anthropic-owned vs provider-routed user agents

Updated the HTTP user-agent helpers so:

  • Anthropic-owned endpoints continue using claude-cli/<compatibility-version>
  • provider-routed non-first-party API traffic uses openclaude-cli/<current-build-version>

Files:

  • src/utils/http.ts

2. Make API client routing follow the actual request target

Updated getAnthropicClient() to pass its already-computed first-party decision into the provider-routed user-agent helper.

This ensures user-agent selection follows the real request routing, including providerOverride, instead of relying only on ambient environment variables.

Files:

  • src/services/api/client.ts

3. Add focused regression coverage

Expanded tests to cover:

  • first-party compatibility traffic
  • Anthropic-owned endpoints under third-party provider environment
  • non-first-party/OpenAI-compatible provider traffic
  • explicit first-party override behavior

Files:

  • src/utils/http.test.ts
  • src/utils/userAgent.test.ts

Why

We needed to fix two opposite problems at the same time:

  1. Anthropic-owned requests must preserve upstream-compatible identity and compatibility versioning so they continue to work with first-party filters and version gates.
  2. OpenAI-compatible and other non-first-party connections should no longer report the compatibility version (99.0.0) as the client version, and should instead surface the actual current build version.

This PR makes that split explicit and request-target-aware.

User Impact

  • Anthropic-owned compatibility-sensitive flows continue to behave like upstream where required.
  • OpenAI-compatible/non-first-party connections now report OpenClaude branding and the current build version instead of the compatibility version.
  • providerOverride requests now use the correct user-agent for the actual target they are routed to.

Validation

Ran:

bun test src/utils/http.test.ts src/utils/userAgent.test.ts
bun run build
node dist/cli.mjs --version

Observed:

  • focused tests passed
  • build completed successfully
  • built artifact reported 0.7.0 (OpenClaude)

Commits

  • 0a1c56c Split public build version from compatibility headers
  • 9f86de0 Route API user agents by actual provider target

jatmn added 3 commits May 1, 2026 18:18
Keep compatibility-sensitive claude-cli/claude-code user agents on MACRO.VERSION while adding a shared public build version helper for MCP-facing metadata.

Update MCP client metadata and MCP user-agent strings to report DISPLAY_VERSION where appropriate without reintroducing first-party version-gate regressions.

Add focused regression tests covering:
- public build version helper behavior
- API client user-agent compatibility behavior
Split Anthropic-owned endpoint user agents from provider-routed API traffic.

Keep compatibility-sensitive Anthropic requests on claude-cli/99.0.0 while using openclaude-cli with the current public build version for non-first-party/OpenAI-compatible connections.

Wire getAnthropicClient() to pass its providerOverride-aware first-party decision into the user-agent helper so per-request routing stays correct.

Expand focused tests to cover first-party compatibility traffic, Anthropic-owned endpoints under third-party env, non-first-party provider traffic, and explicit first-party override behavior.
@jatmn
Copy link
Copy Markdown
Collaborator Author

jatmn commented May 2, 2026

@kevincodex1 we cant merge this without confirmation from moonshot that they whitelisted openclaude-cli or all kimicode connections are blocked by their servers with this PR.

@techbrewboss
Copy link
Copy Markdown
Collaborator

Looks good to merge from the code review side. I verified the focused user-agent tests, API client/shim routing tests, and build all pass.

Holding off on approval per the PR note until the KimiCode provider confirmation is available.

Copy link
Copy Markdown
Collaborator

@gnanam1990 gnanam1990 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code-side review (not approving — respecting the merge-block in the PR description until @kevincodex1 has the moonshot/KimiCode whitelist confirmation).

Verified locally

  • bun test src/utils/http.test.ts src/utils/userAgent.test.ts → 6 pass, 0 fail
  • Diff is clean and tightly scoped to user-agent splitting

Code is sound

  1. getUserAgent() (compatibility) and getProviderApiUserAgent() (provider-routed) are now properly separated, with MACRO.VERSION (99.0.0 compat) reserved for first-party and getPublicBuildVersion() (DISPLAY_VERSION → real build) for non-first-party. The claude-cliopenclaude-cli token swap on third-party is exactly what the rebrand wants.
  2. First-party decision is now driven by shouldUseFirstPartyAnthropicAuth(providerOverride) — same function gating auth — so per-request routing and UA selection cannot diverge. Good fix for the providerOverride-aware case.
  3. MCP version field switched to getPublicBuildVersion() while the MCP name: 'claude-code' is preserved (correctly — that field is documented as the upstream feature-gating identifier).
  4. No red flags: no tengu_*, no USER_TYPE === 'ant' re-introduced (the test only uses USER_TYPE as the existing env passthrough), no new network calls, no new deps, no provider routing changes beyond the UA helper rewiring.

One thing worth checking before lifting the block

The block is real — any provider that whitelisted by exact UA string (KimiCode, but possibly others) will start being rejected once non-first-party flips to openclaude-cli/<DISPLAY_VERSION>. Worth a quick scan beyond moonshot:

  • Groq, Mistral, MiniMax, AI/ML API, Hicap (#979), iFlytek (#824), NVIDIA NIM (#960) — anyone we've heard from about UA filtering?

If only moonshot is gated, the moonshot confirmation alone is enough. If other providers do UA filtering, may want to pre-notify them or hold for a coordinated rollout.

Holding off on approve until @kevincodex1 / @jatmn give the green light.

Copy link
Copy Markdown
Collaborator

@Vasanthdev2004 Vasanthdev2004 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Targeted maintainer triage review of the current head ($short).

Verdict: Needs changes

Blocking issue:

  1. GitHub reports this branch as DIRTY / conflicting with main, so it cannot be merged or final-approved as-is. Please rebase or merge latest main, resolve the conflicts, and rerun the relevant checks.

I did not do a full code review because the current branch state is not mergeable. Happy to re-review once the branch is clean.

@jatmn
Copy link
Copy Markdown
Collaborator Author

jatmn commented May 9, 2026

I pushed a follow-up update that keeps the original compatibility identity for the Kimi Code provider while preserving the new openclaude-cli identity for other non-first-party provider traffic.

What changed:

  • Synced the branch with latest upstream/main.
  • Resolved the merge conflict in src/services/api/client.ts by keeping both upstream's effort-routing changes and this PR's provider-aware user-agent routing.
  • Added a Kimi Code-specific fallback so requests from the selected /provider route kimi-code continue using claude-cli/<compatibility-version>.
  • Kept the fallback narrow: it is keyed off the selected provider route identity, not model name, base URL, or generic Moonshot/Kimi-compatible traffic.
  • Avoided adding any new persistent env state or broad URL-based detection.
  • Kept providerOverride requests from inheriting the KimiCode fallback, since those requests are routed to an explicit per-request target.
  • Updated focused user-agent tests to cover the KimiCode provider-route behavior.

Latest relevant commits:

  • 589eee4 - Merge latest upstream/main into api-client-version
  • 580174e - Preserve Kimi Code compatibility user agent
  • c2fecc6 - Narrow Kimi Code user agent fallback

Validation:

bun install
bun run build
bun run smoke
bun test src/utils/http.test.ts src/utils/userAgent.test.ts

Results:

  • bun install completed successfully and installed dependencies.
  • bun run build passed and built both dist/cli.mjs and dist/sdk.mjs.
  • bun run smoke passed and reported 0.9.2 (OpenClaude).
  • Focused user-agent tests passed: 7 pass, 0 fail, 14 expect() calls.

Build note: the build script printed warnings about external entries not listed in package.json and marked them as "may be ok"; external-list validation still passed.

@jatmn jatmn requested review from Vasanthdev2004 and gnanam1990 May 9, 2026 00:07
@jatmn jatmn self-assigned this May 9, 2026
@Vasanthdev2004
Copy link
Copy Markdown
Collaborator

Targeted re-review of current head c2fecc6, focused on the latest Kimi Code fallback and provider-routed user-agent behavior.

Verdict: Blocked on maintainer decision

Code-side check:

  • The known Kimi Code risk is now narrowed to providerRouteId === 'kimi-code', so Kimi Code profile traffic keeps the upstream-compatible claude-cli/<compat-version> token.
  • Other non-first-party provider API traffic now gets openclaude-cli/<public-build-version>.
  • providerOverride does not inherit the Kimi fallback, which keeps explicit per-request routing from accidentally changing identity based on the active profile.
  • Ran bun test ./src/utils/http.test.ts ./src/utils/userAgent.test.ts: 7/7 passing.

I do not see a code-level blocker in the latest fallback, but I still think final merge should be a maintainer/product decision because this intentionally changes outbound client identity for provider traffic. If we are aligned that non-first-party provider traffic should identify as OpenClaude by default, this looks ready from the targeted code review side.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants